<?php

namespace api\modules\v1\forms\member;

use common\models\base\Department;
use common\models\base\Job;
use common\models\base\Project;
use common\models\member\Attr;
use common\models\member\Member;
use common\helpers\ValidatorHelper;
use common\models\rbac\Role;
use services\base\DepartmentService;
use services\base\ProjectService;
use services\member\MemberDepartmentService;
use services\member\MemberService;
use services\rbac\RoleService;
use services\rbac\UserRoleService;
use yii\base\Model;

/**
 * Class MemberForm
 * @package api\modules\v1\forms\member
 */
class MemberForm extends Model
{
    /**
     * @var int $id ID
     * @var string $username 姓名
     * @var string $mobile 手机号
     * @var string $password 密码
     * @var array $project_ids 项目
     * @var array $department_ids 部门
     * @var array $role_ids 角色
     * @var int $job_id 岗位
     * @var int $status 状态
     * @var string $new_password 新密码
     * @var string $confirm_password 确认密码
     */
    public $id;
    public $username;
    public $mobile;
    public $password;
    public $project_ids;
    public $department_ids;
    public $role_ids;
    public $job_id;
    public $status;
    public $new_password;
    public $confirm_password;

    /**
     * @var Member $_memberInfo
     * @var Attr $_memberAttrInfo
     * @var Project[] $_projectList
     * @var Department[] $_departmentList
     * @var Role[] $_roleList
     * @var Job $_jobInfo
     * @var Project[] $_haveProjectList
     */
    protected $_memberInfo;
    protected $_memberAttrInfo;
    protected $_projectList;
    protected $_departmentList;
    protected $_roleList;
    protected $_jobInfo;
    protected $_oldRoleIds;
    protected $_haveProjectList;


    public function rules()
    {
        return [
            // 参数验证
            [['username', 'mobile', 'password', 'project_ids', 'department_ids', 'role_ids', 'status'], 'required', 'message' => '{attribute}不能为空', 'on' => ['create']],
            [['id', 'username', 'mobile', 'project_ids', 'department_ids', 'role_ids', 'status'], 'required', 'message' => '{attribute}不能为空', 'on' => ['edit']],
            [['id'], 'required', 'message' => '{attribute}不能为空', 'on' => ['delete']],
            [['id', 'password', 'new_password', 'confirm_password'], 'required', 'message' => '{attribute}不能为空', 'on' => ['update_password']],

            [['id'], 'checkId', 'skipOnEmpty' => false, 'on' => ['edit', 'delete', 'update_password']],
            [['username'], 'checkUsername', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['mobile'], 'checkMobile', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['password'], 'checkPassword', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['project_ids'], 'checkProjectIds', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['department_ids'], 'checkDepartmentIds', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['role_ids'], 'checkRoleIds', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['job_id'], 'checkJobId', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['status'], 'checkStatus', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['password'], 'checkOldPassword', 'skipOnEmpty' => false, 'on' => ['update_password']],
            [['new_password'], 'checkNewPassword', 'skipOnEmpty' => false, 'on' => ['update_password']],
            [['confirm_password'], 'checkConfirmPassword', 'skipOnEmpty' => false, 'on' => ['update_password']],
        ];
    }

    public function scenarios()
    {
        $scenarios = parent::scenarios();

        // 新增
        $scenarios['create'] = ['username', 'mobile', 'password', 'project_ids', 'department_ids', 'role_ids', 'job_id', 'status'];

        // 编辑
        $scenarios['edit'] = ['id', 'username', 'mobile', 'password', 'project_ids', 'department_ids', 'role_ids', 'job_id', 'status'];

        // 删除
        $scenarios['delete'] = ['id'];

        // 修改密码
        $scenarios['update_password'] = ['id', 'password', 'new_password', 'confirm_password'];

        return $scenarios;
    }

    /**
     * @return array
     */
    public function attributeLabels()
    {
        return [
            'id' => '用户ID',
            'username' => '用户名',
            'mobile' => '手机号',
            'password' => '密码',
            'project_ids' => '项目',
            'department_ids' => '部门',
            'role_ids' => '角色',
            'job_id' => '岗位',
            'new_password' => '新密码',
            'confirm_password' => '确认密码',
        ];
    }

    /**
     * 检验用户ID
     * @param $attribute
     * @return void
     */
    public function checkId($attribute)
    {
        if ($this->hasErrors()) {
            return;
        }
        if ($this->getScenario() != 'update_password' && $this->checkOpAdminLimit($attribute) === false) {
            return;
        }

        $member = $this->getMember();
        if (empty($member)) {
            $this->addError($attribute, '用户不存在');
            return;
        }
        if ($this->getScenario() != 'update_password' && $member->super_type == Member::SUPER_TYPE_SUPER_ADMIN) {
            $this->addError($attribute, '无法操作超管用户');
            return;
        }
        if ($member->status == Member::STATUS_DELETE) {
            $this->addError($attribute, '用户已删除，无法操作');
            return;
        }
    }

    /**
     * 检验姓名
     * @param $attribute
     * @return void
     */
    public function checkUsername($attribute)
    {
        if ($this->hasErrors()) {
            return;
        }
        if ($this->checkOpAdminLimit($attribute) === false) {
            return;
        }

        if (mb_strlen($this->username) > 20) {
            $this->addError($attribute, '用户名错误[1-20位]');
            return;
        }
    }

    /**
     * 检验手机号
     * @param $attribute
     * @return void
     */
    public function checkMobile($attribute)
    {
        if ($this->hasErrors()) {
            return;
        }

        if (ValidatorHelper::validateMobile($this->mobile) === false) {
            $this->addError($attribute, '请输入正确手机号');
            return;
        }
        if ($this->getScenario() == 'edit') {
            $member = $this->getMember();
            if ($member->mobile == $this->mobile) {
                return;
            }
        }
        if (Member::findOne(['mobile' => $this->mobile, 'status' => [Member::STATUS_INVALID, Member::STATUS_ENABLE]])) {
            $this->addError($attribute, '手机号已绑定，请更换手机号');
            return;
        }
    }

    /**
     * 检验密码
     * @param $attribute
     * @return void
     */
    public function checkPassword($attribute)
    {
        if ($this->hasErrors()) {
            return;
        }
        // 编辑不填密码，则不修改
        if (empty($this->password) && $this->getScenario() == 'edit') {
            return;
        }

        if (!ValidatorHelper::validatePassword($this->password)) {
            $this->addError($attribute, '用户密码错误[同时包含数字和字母，最少8位字符]');
            return;
        }
    }

    /**
     * 检验项目
     * @param $attribute
     * @return void
     */
    public function checkProjectIds($attribute)
    {
        if ($this->hasErrors()) {
            return;
        }

        $haveProjectList = $this->getHaveProjectList();
        foreach ($haveProjectList as $row) {
            if ($row['disabled'] && in_array($row['value'], $this->project_ids) === false) {
                $this->addError($attribute, '无权限删除非自己绑定项目');
                return;
            }
        }
        $haveIds = array_column($haveProjectList, 'value');
        $projects = ProjectService::getNormalListByIds($this->project_ids);
        foreach ($projects as $project) {
            if (in_array($project->id, $haveIds) === false) {
                $this->addError($attribute, '无权限选择非自己绑定项目');
                return;
            }

            if ($project->status == Project::STATUS_INVALID && $this->getScenario() == 'create') {
                $this->addError($attribute, '所选项目存在禁用，请刷新后重试');
                return;
            }
        }
        $this->_projectList = $projects;
    }

    /**
     * 检验部门
     * @param $attribute
     * @return void
     */
    public function checkDepartmentIds($attribute)
    {
        if ($this->hasErrors()) {
            return;
        }

        $departments = DepartmentService::getNormalCacheListByIds($this->department_ids);
        foreach ($departments as $department) {
            if ($department->status == Department::STATUS_INVALID) {
                if ($this->getScenario() == 'create' || !in_array($department->id, $this->getMemberAttr()->department_id)) {
                    $this->addError($attribute, '所选部门存在禁用，请刷新后重试');
                    return;
                }
            }
        }
        $this->_departmentList = $departments;
    }

    /**
     * 检验角色
     * @param $attribute
     * @return void
     */
    public function checkRoleIds($attribute)
    {
        if ($this->hasErrors()) {
            return;
        }

        $departmentList = $this->getDepartmentList();
        $selectRoleIds = $defaultRoleIds = [];
        foreach ($departmentList as $department) {
            $selectRoleIds = array_merge($selectRoleIds, $department->select_role_ids);
            $defaultRoleIds[] = $department->default_role_id;
        }
        if (array_diff($this->role_ids, $selectRoleIds)) {
            $this->addError($attribute, '所选角色超出部门角色范围，请刷新后重试');
            return;
        }

        $this->_oldRoleIds = $roleIds = UserRoleService::getUserRoleIds($this->id);
        $roles = RoleService::getNormalCacheListByIds(array_diff($this->role_ids, $defaultRoleIds));
        foreach ($roles as $role) {
            if ($role->status == Role::STATUS_INVALID) {
                if ($this->getScenario() == 'create' || !in_array($role->id, $roleIds)) {
                    $this->addError($attribute, '所选角色存在禁用，请刷新后重试');
                    return;
                }
            }
        }
        $this->_roleList = $roles;
    }

    /**
     * 检验岗位
     * @param $attribute
     * @return void
     */
    public function checkJobId($attribute)
    {
        if ($this->hasErrors()) {
            return;
        }
        if (empty($this->job_id)) {
            return;
        }

        $job = $this->getJob();
        if (empty($job)) {
            $this->addError($attribute, '岗位不存在');
            return;
        }
        if ($this->getScenario() == 'edit' && $this->getMemberAttr()->job_id == $this->job_id) {
            return;
        }
        if ($job->status == Job::STATUS_DELETE) {
            $this->addError($attribute, '岗位已删除，无法操作');
            return;
        }
        if ($job->status == Job::STATUS_INVALID) {
            $this->addError($attribute, '岗位已禁用，无法操作');
            return;
        }
    }

    /**
     * 检验类型
     * @param $attribute
     * @return void
     */
    public function checkStatus($attribute)
    {
        if ($this->hasErrors()) {
            return;
        }

        if (!in_array($this->status, [Member::STATUS_INVALID, Member::STATUS_ENABLE])) {
            $this->addError($attribute, '类型错误');
            return;
        }
    }

    /**
     * 检验原密码
     * @param $attribute
     * @return void
     */
    public function checkOldPassword($attribute)
    {
        if ($this->hasErrors()) {
            return;
        }

        $member = $this->getMember();
        if (\Yii::$app->security->validatePassword($this->password, $member->password_hash) === false) {
            $this->addError($attribute, '原密码错误');
            return;
        }
    }

    /**
     * 检验新密码
     * @param $attribute
     * @return void
     */
    public function checkNewPassword($attribute)
    {
        if ($this->hasErrors()) {
            return;
        }

        if (!ValidatorHelper::validatePassword($this->new_password)) {
            $this->addError($attribute, '新密码错误[同时包含数字和字母，最少8位字符]');
            return;
        }
    }

    /**
     * 检验确认密码
     * @param $attribute
     * @return void
     */
    public function checkConfirmPassword($attribute)
    {
        if ($this->hasErrors()) {
            return;
        }

        if ($this->confirm_password != $this->new_password) {
            $this->addError($attribute, '两次密码不相同');
            return;
        }
    }

    /**
     * 获取用户信息
     * @return Member|null
     */
    public function getMember(): ?Member
    {
        if (is_null($this->_memberInfo)) {
            $this->_memberInfo = Member::findOne($this->id);
        }
        return $this->_memberInfo;
    }

    /**
     * 获取用户信息
     * @return Attr|null
     */
    public function getMemberAttr(): ?Attr
    {
        if (is_null($this->_memberAttrInfo)) {
            $this->_memberAttrInfo = Attr::findOne(['member_id' => $this->id]);
        }
        return $this->_memberAttrInfo;
    }

    /**
     * 获取岗位
     * @return Job|null
     */
    public function getJob(): ?Job
    {
        if (is_null($this->_jobInfo)) {
            $this->_jobInfo = Job::findOne($this->job_id);
        }
        return $this->_jobInfo;
    }

    /**
     * 获取真实项目列表
     * @return Project[]
     */
    public function getProjectList(): array
    {
        return $this->_projectList ?: [];
    }

    /**
     * 获取部门列表
     * @return Department[]
     */
    public function getDepartmentList(): array
    {
        return $this->_departmentList ?: [];
    }

    /**
     * 获取真实角色列表
     * @return Role[]
     */
    public function getRoleList(): array
    {
        return $this->_roleList ?: [];
    }

    /**
     * 获取原角色IDs
     * @return array
     */
    public function getOldRoleIds(): array
    {
        return $this->_oldRoleIds ?: [];
    }

    /**
     * 检验操作人账号权限
     * @return bool
     */
    public function checkOpAdminLimit($attribute): bool
    {
        /*if (\Yii::$app->user->identity->member->super_type == Member::SUPER_TYPE_NORMAL) {
            $this->addError($attribute, '非管理员无法操作');
            return false;
        }*/
        return true;
    }

    /**
     * 检验操作人拥有项目列表
     * @return array
     */
    public function getHaveProjectList(): array
    {
        if (is_null($this->_haveProjectList)) {
            $attr = $this->getMemberAttr();
            $this->_haveProjectList =  ProjectService::getEditCondition($attr->project_id ?? null);
        }
        return $this->_haveProjectList;
    }

    /**
     * 检验操作人拥有项目列表
     * @return array
     */
    public function getD(): array
    {
        if (is_null($this->_haveProjectList)) {


            $attr = $this->getMemberAttr();
            $this->_haveProjectList =  ProjectService::getEditCondition($attr->project_id ?? null);
        }
        return $this->_haveProjectList;
    }
}